﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Threading;
using Figgle;
using Log.Manager.Core;
using MRC.VM.ConsoleApp.Common;
using Newtonsoft.Json;
using SocketConnect.Core;

namespace MRC.VM.ConsoleApp
{
    class Program
    {
        private static bool IsMissionRunning = true;
        private static int Index = 0;
        private static int TimeIndex = 0;
        private static bool IsCansemiMission = false;
        private static Target Target;
        private static SocketConnection MRS_Connector = new SocketConnection();
        private static clsLogManager LogManager = new clsLogManager();
        static void Main(string[] args)
        {
            var runDir = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);
            LogManager.LogPath = $"{runDir}\\Log";
            LogManager.LogAgeDays = 10;
            LogManager.LogName = "MRC_VM_ConsoleApp";
            LogManager.MaxLineCharCount = 5000;
            LogManager.MaxLogFileSize_MB = 100;
            LogManager.ShowMilliSecond = true;

            MRS_Connector.ReceiveData += new SocketConnection.SocketDataEventHandel(MRC_Connection_ReceiveData);
            MRS_Connector.Connected += new SocketConnection.SocketEventHandel(MRC_Connection_Connected);
            // var b = MRC_Conn.Connect("192.168.1.101", 8990);

            Console.WriteLine(FiggleFonts.Standard.Render("Welcome to Virtual MRC"));
            Console.WriteLine("First of all, please select the MRC environment.");
            Console.WriteLine("1. Load & start general mission.");
            Console.WriteLine("2. Load & start cansemi mission.");
            Console.WriteLine("3. Exit.");
            Console.WriteLine();

            while (true)
            {
                try
                {
                    var input = Console.ReadLine();
                    if (Convert.ToInt16(input) == 1)
                    {
                        Target = LoadTarget();
                        var connected = MRS_Connector.Connect(Target.IP, Target.Port);
                        if (connected)
                        {
                            if (Target.Loop >= -1)
                            {
                                var mission = Target.MissionPool[Index];
                                if (mission.Action == "P")
                                {
                                    SendData(MRS_Connector, $"{mission.Action}1 TID=00000001 MISSIONID={mission.MissionId} SRC1={mission.Goal} LOT1={mission.Lot} QTY1={mission.Quantity}");
                                }
                                else if(mission.Action == "D")
                                {
                                    SendData(MRS_Connector, $"{mission.Action}1 TID=00000001 MISSIONID={mission.MissionId} LOT1={mission.Lot} QTY1={mission.Quantity} DES1={mission.Goal}");
                                }
                                
                                Index++;
                            }
                            else
                            {
                                throw new Exception("Unexpected loop set.");
                            }

                            
                        }
                    }
                    else if (Convert.ToInt16(input) == 2)
                    {
                        IsCansemiMission = true;

                        Target = LoadCansemiTarget();

                        var connected = MRS_Connector.Connect(Target.IP, Target.Port);
                        if (connected)
                        {
                            if (Target.Loop >= -1)
                            {
                                Console.WriteLine("============================================================================");
                                Console.WriteLine(FiggleFonts.Standard.Render($"# {TimeIndex+1}"));

                                var mission1 = Target.MissionPool[Index];
                                var mission2 = Target.MissionPool[Index+1];

                                SendData(MRS_Connector, $"{mission1.Action}{mission1.Position}{mission2.Action}{mission2.Position} TID=00000001 MISSIONID={DateTime.Now.ToString("yyyyMMddmmDDss")} SRC1={mission1.Goal} LOT1={mission1.Lot} QTY1={mission1.Quantity} DES1={mission2.Goal}");
                                
                                Index += 2;
                                if (Index >= Target.MissionPool.Count)
                                {
                                    Index = 0;
                                }

                                TimeIndex ++;
                                if (TimeIndex >= Target.Loop - 1 && Target.Loop > -1)
                                {
                                    TimeIndex = 0;
                                }
                                
                                // SendData(MRS_Connector, $"P1D1 TID=00000001 MISSIONID={mission.MissionId} SRC1={mission.Source} LOT1={mission.Lot} QTY1={mission.Quantity} DES1={mission.Destination}");
                            }
                            else
                            {
                                throw new Exception("Unexpected loop set.");
                            }
                        }
                    }
                    else if (Convert.ToInt16(input) == 3)
                    {
                        break;
                    }
                }
                catch (System.Exception ex)
                {
                    Console.WriteLine(ex.Message);
                }
                Console.WriteLine();
            }
        }
        private static Target LoadTarget()
        {
            var runDir = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);
            return JsonConvert.DeserializeObject<Target>(File.ReadAllText(runDir+"\\target.json"));
        }
        private static Target LoadCansemiTarget()
        {
            var runDir = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);
            return JsonConvert.DeserializeObject<Target>(File.ReadAllText(runDir+"\\cansemi-target.json"));
        }
        private static void MRC_Connection_ReceiveData(SocketDataEventArgs e, object sender)
        {
            var data = e.Receive_Data;
            Console.WriteLine($"Received: {data}");
            LogManager.WriteLog(data+Environment.NewLine);
            
            try
            {
                var parms = data.Split(' ').ToList();
                parms.RemoveAt(parms.Count-1);
                Func<string, object> act = p =>
                {
                    try
                    {
                        var parm = p.Split('=');
                        return new { Key = parm[0], Value = parm[1] };
                    }
                    catch (Exception)
                    {
                        return null;
                    }
                };

                var dict = parms.Where(o => o != null).Select(o => act(o)).ToDictionary<object, string, string>(o => ((dynamic)o).Key,o => ((dynamic)o).Value);
                
                var conn = (SocketConnection)sender;
                switch (dict["Event"].ToUpper())
                {
                    case "COMPLETEMISSION":
                        Thread.Sleep(1000);

                        if (IsCansemiMission)
                        {
                            if (Target.Loop == -1)
                            {
                                Console.WriteLine("============================================================================");
                                Console.WriteLine(FiggleFonts.Standard.Render($"# {TimeIndex+1}"));

                                LogManager.WriteLog("============================================================================");
                                LogManager.WriteLog(FiggleFonts.Standard.Render($"# {TimeIndex+1}{Environment.NewLine}"));

                                var mission1 = Target.MissionPool[Index];
                                var mission2 = Target.MissionPool[Index+1];

                                SendData(MRS_Connector, $"{mission1.Action}{mission1.Position}{mission2.Action}{mission2.Position} TID=00000001 MISSIONID={DateTime.Now.ToString("yyyyMMddmmDDss")} SRC1={mission1.Goal} LOT1={mission1.Lot} QTY1={mission1.Quantity} DES1={mission2.Goal}");
                                
                                Index += 2;
                                if (Index >= Target.MissionPool.Count)
                                {
                                    Index = 0;
                                }
                                TimeIndex ++;
                            }
                            else if(Target.Loop > 0)
                            {
                                // if(TimeIndex < Target.Loop && IsMissionRunning)
                                // {
                                //     var mission = Target.MissionPool[Index];
                                //     SendData(MRS_Connector, $"P1D1 TID=00000001 MISSIONID={mission.MissionId} SRC1={mission.Source} LOT1={mission.Lot} QTY1={mission.Quantity} DES1={mission.Destination}");

                                //     Index ++;
                                //     TimeIndex ++;
                                //     if (Index >= Target.MissionPool.Count)
                                //     {
                                //         Index = 0;
                                //     }
                                // }
                                Console.WriteLine("============================================================================");
                                Console.WriteLine(FiggleFonts.Standard.Render($"# {TimeIndex+1}"));

                                LogManager.WriteLog("============================================================================");
                                LogManager.WriteLog(FiggleFonts.Standard.Render($"# {TimeIndex+1}{Environment.NewLine}"));

                                var mission1 = Target.MissionPool[Index];
                                var mission2 = Target.MissionPool[Index+1];

                                SendData(MRS_Connector, $"{mission1.Action}{mission1.Position}{mission2.Action}{mission2.Position} TID=00000001 MISSIONID={DateTime.Now.ToString("yyyyMMddmmDDss")} SRC1={mission1.Goal} LOT1={mission1.Lot} QTY1={mission1.Quantity} DES1={mission2.Goal}");
                                
                                Index += 2;
                                if (Index >= Target.MissionPool.Count)
                                {
                                    Index = 0;
                                }

                                TimeIndex ++;
                                if (TimeIndex >= Target.Loop - 1)
                                {
                                    TimeIndex = 0;
                                }
                            }
                        }
                        else
                        {
                            if (Target.Loop == -1)
                            {
                                var mission = Target.MissionPool[Index];
                                // SendData(MRS_Connector, $"P1D1 TID=00000001 MISSIONID={mission.MissionId} SRC1={mission.Source} LOT1={mission.Lot} QTY1={mission.Quantity} DES1={mission.Destination}");
                                if (mission.Action == "P")
                                {
                                    SendData(MRS_Connector, $"{mission.Action}1 TID=00000001 MISSIONID={mission.MissionId} SRC1={mission.Goal} LOT1={mission.Lot} QTY1={mission.Quantity}");
                                }
                                else if(mission.Action == "D")
                                {
                                    SendData(MRS_Connector, $"{mission.Action}1 TID=00000001 MISSIONID={mission.MissionId} LOT1={mission.Lot} QTY1={mission.Quantity} DES1={mission.Goal}");
                                }

                                Index ++;
                                if (Index > Target.MissionPool.Count - 1)
                                {
                                    Index = 0;
                                }
                            }
                            else if(Target.Loop > 0)
                            {
                                // if(TimeIndex < Target.Loop && IsMissionRunning)
                                // {
                                //     var mission = Target.MissionPool[Index];
                                //     SendData(MRS_Connector, $"P1D1 TID=00000001 MISSIONID={mission.MissionId} SRC1={mission.Source} LOT1={mission.Lot} QTY1={mission.Quantity} DES1={mission.Destination}");

                                //     Index ++;
                                //     TimeIndex ++;
                                //     if (Index >= Target.MissionPool.Count)
                                //     {
                                //         Index = 0;
                                //     }
                                // }
                            }
                        }
                        break;
                    default:
                        break;
                }
                Console.WriteLine();
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
        }
        private static void MRC_Connection_Connected(SocketEventArgs e, object sender)
        {
            Console.WriteLine("MRS Connected");
            Console.WriteLine();
        }
        private static void SendData(SocketConnection conn, string msg)
        {
            conn.SendData(msg);
            Console.WriteLine($"Sent: {msg}");
        }
    }
}
